
package com.vision.sales.sv.serv.rpc;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sencha.gxt.data.shared.loader.PagingLoadResult;
import com.sencha.gxt.data.shared.loader.PagingLoadResultBean;
import com.vision.core.cm.data.Domain;
import com.vision.core.cm.exception.RpcException;
import com.vision.core.sv.db.mgr.IDataManager;
import com.vision.core.sv.db.mgr.ISimpleCriteria;
import com.vision.core.sv.serv.rpc.AbstractServiceImpl;
import com.vision.core.sv.util.CollectionUtils;
import com.vision.sales.cl.ui.component.TransactionLoadConfig;
import com.vision.sales.cm.data.SalesPermissions;
import com.vision.sales.cm.data.TransactionStatus;
import com.vision.sales.cm.db.data.DeliveryReceipt;
import com.vision.sales.cm.serv.rpc.DeliveryReceiptService;
import com.vision.sales.sv.util.TransactionHelper;

/**
 * 
 * @author Mark
 *s
 */
@Service("delivery_receipts")
public class DeliveryReceiptServiceImpl extends AbstractServiceImpl<DeliveryReceipt> implements DeliveryReceiptService {

	private static final long serialVersionUID = 1L;
	
	private static final Logger log = LoggerFactory.getLogger(DeliveryReceiptServiceImpl.class);
	
	public DeliveryReceiptServiceImpl() {
		initGilead();
	}

	@Autowired
	@Qualifier("deliveryReceiptManager")
	@Override
	public void setDataManager(IDataManager<DeliveryReceipt> dataManager) {
		super.setDataManager(dataManager);
	}
	
	@Override
	protected Domain getDomain() {
		return Domain.DELIVERY_RECEIPT;
	}
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Override
	public List<DeliveryReceipt> getAll() throws RpcException {
		checkPermissions(SalesPermissions.ViewDeliveryReceipt);
		return super.getAll();
	}
	
	@SuppressWarnings("unchecked")
	public PagingLoadResult<DeliveryReceipt> getList(TransactionLoadConfig config) throws RpcException {
		checkPermissions(SalesPermissions.ViewDeliveryReceipt);
		
		ISimpleCriteria crit = TransactionHelper.createCriteria(DeliveryReceipt.class, config);
		if (config.isInvoiced() != null) {
			if (config.isInvoiced())
				crit.notNull("salesInvoice.id");
			else
				crit.isNull("salesInvoice.id");
		}
		List<DeliveryReceipt> list = (List<DeliveryReceipt>) TransactionHelper.getList(crit, config, getTemplate());
		
		ISimpleCriteria countCrit = TransactionHelper.createCountCriteria(DeliveryReceipt.class, config);
		if (config.isInvoiced() != null) {
			if (config.isInvoiced())
				countCrit.notNull("salesInvoice.id");
			else
				countCrit.isNull("salesInvoice.id");
		}
		Long count = (Long) getTemplate().findByCriteria(countCrit.getDetached()).get(0);
		
		PagingLoadResultBean<DeliveryReceipt> result = new PagingLoadResultBean<DeliveryReceipt>(list, count.intValue(), config.getOffset());
		return result;
	}
	
	@Transactional
	@Override
	public DeliveryReceipt create(DeliveryReceipt receipt) throws RpcException {
		checkPermissions(SalesPermissions.CreateDeliveryReceipt);
		checkFieldUnique("drNo", receipt.getDrNo(), "D/R No.");
		
		// Set to as POSTED by default
		receipt.setStatus(TransactionStatus.POSTED);
		
		DeliveryReceipt result = super.create(receipt);
		
		logCreate(result);
		
		return result;
	}
	
	@Transactional
	@Override
	public DeliveryReceipt update(DeliveryReceipt receipt) throws RpcException {
		checkPermissions(SalesPermissions.UpdateDeliveryReceipt);
		
		DeliveryReceipt existing = checkExisting(receipt.getId());
		// Ensure that the sales invoice is set to its current value
		if (existing.getSalesInvoice() != null)
			receipt.setSalesInvoice(existing.getSalesInvoice());
		
		DeliveryReceipt result = super.update(receipt);
		
		logUpdate(existing, result);
		
		return result;
	}
	
	@Transactional
	@Override
	public DeliveryReceipt delete(DeliveryReceipt receipt) throws RpcException {
		checkPermissions(SalesPermissions.DeleteDeliveryReceipt);
		
		DeliveryReceipt existing = checkExisting(receipt.getId());
		if (existing.getSalesInvoice() != null && existing.getSalesInvoice().getId() != null)
			throw new RpcException("The delivery receipt has been invoiced. It cannot be deleted.");
		
		DeliveryReceipt result = super.delete(receipt);
		
		logDelete(result);
		
		return result;
	}
	
	@Transactional
	@Override
	public List<DeliveryReceipt> voidReceipts(List<DeliveryReceipt> receipts) throws RpcException {
		checkPermissions(SalesPermissions.VoidDeliveryReceipt);
		
		List<Long> ids = CollectionUtils.listFrom(receipts, "getId");
		List<DeliveryReceipt> existingReceipts = getDataManager().getByIds(DeliveryReceipt.COL_ID, ids);
		List<DeliveryReceipt> results = new ArrayList<DeliveryReceipt>(existingReceipts.size());
		
		for (DeliveryReceipt existing : existingReceipts) {
			// If already invoiced, fail
			if (existing.getSalesInvoice() != null && existing.getSalesInvoice().getId() != null)
				throw new RpcException("The delivery receipt '" + existing.getDrNo() + "' has been invoiced. It cannot be voided.");

			log.debug("Voiding delivery receipt {}...", existing.getDrNo());
			existing.setStatus(TransactionStatus.VOIDED);
			DeliveryReceipt result = getDataManager().update(existing);
			
			logUpdate(existing, result);
			
			results.add(result);
		}
		
		return results;
	}
	
}
